﻿/*
# -*- coding: utf-8 -*-
# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.

# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.

# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.

# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.

# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.

# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.

# 注意：

# 若希望将本代码用于商业用途，需先联系作者并获得明确授权。
# 作者不对因使用本代码引发的任何直接或间接损失负责。
# 如有违反上述条款的行为，作者保留追究法律责任的权利。

# 免责声明：
# 请尊重知识产权，遵循相关法律法规。

# Notice:
# If you wish to use this code for commercial purposes, you must contact the author and obtain explicit authorization.
# The author is not responsible for any direct or indirect losses caused by the use of this code.
# If any of the above terms are violated, the author reserves the right to pursue legal action.
# Disclaimer:
# Please respect intellectual property rights and comply with relevant laws and regulations.
*/
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using System.Linq;
using System.Collections;
using EventManager;

public class GameController : SingletonMonoBehaviour<GameController>
{
    // [SerializeField]
    //Transform itemPrefab;     // prefab of item

    public Transform gridParent;
    CellData[,] cellDatas;
    // mapdata
    List<CellItem> cellItems = new List<CellItem>();
    //init data;         // list object item

    [SerializeField]
    LineConnect line;
    //Draw line connect

    public int width, height;
    //  public float minx, miny;
    GameMgr gameMgr;
    CellItem firstSelected;
    // storage item first selected
    public float cellWidth, cellHeight;
    // cell width and height
    float timePlay;
    MoveMode moveMode;

    [SerializeField]
    RectTransform rectGrid;

    [SerializeField]
    Sprite[] sprites;

    private string videoAdid = "5t5k71mqgsh1hebv8q";
    /// <summary>
    /// Init game
    /// </summary>
    /// <param name="_width"></param>
    /// <param name="_height"></param>
    /// <param name="_typeCount"></param>
    public void InitMap(GameMgr gameMgr, Level levelData, MoveMode _moveMode)
    {
        Reset();

        this.width = levelData.width + 2;
        this.height = levelData.height + 2;
        this.gameMgr = gameMgr;
        this.moveMode = _moveMode;

        GenMap();
        SortList();
    }

    public void GoHome()
    {
        Reset();
        UIManager.Instance.ShowPage("LevelPage");
    }

    void Reset()
    {
        firstSelected = null;
        line.gameObject.SetActive(false);
        //  dict = null;
        //cellDatas = null;
        // cellItems = null;
        if (cellItems == null)
        {
            cellItems = new List<CellItem>();
        }
        foreach (CellItem item in cellItems)
        {
            if (item.gameObject.activeSelf)
                ContentMgr.Instance.Despaw(item.gameObject);
        }
        cellItems.Clear();
    }

    public Vector2 GetPos(int posX, int posY)
    {
        var x = cellWidth * (posX - (width - 2) / 2f - .5f) * (1 - 1 / 20f);

        var y = cellHeight * (posY - (height - 2) / 2f - .5f) * (1 - 1 / 20f);
        return new Vector2(x, y);
    }

    /// <summary>
    /// Gen map
    /// </summary>
    void GenMap()
    {
        if (width * height % 2 != 0)     //  the total must be even
        {
            Debug.LogError("Error");
            return;
        }
        cellDatas = new CellData[width, height];            //init data
        //cellItems.Clear();
//        Debug.Log(rectGrid.rect.width + " "+rectGrid.rect.height);
        int tmpCellH = (int)(rectGrid.rect.height / (height - 2));    // screen height is 320

        int tmpCellW = (int)(rectGrid.rect.width / (width - 2));    // screen height is 320

        if (tmpCellW > tmpCellH * 0.825f)
        {
            cellHeight = tmpCellH;    // screen height is 320
            cellWidth = (int)(cellHeight * 0.825f);
        }
        else
        {
            cellWidth = tmpCellW;
            cellHeight = (int)(cellWidth / 0.825f);
        }


        //   minx = -width * cellWidth / 2;
        //  miny = -height * cellHeight / 2;

        int length = (width - 2) * (height - 2);
        List<int> pool = new List<int>();

        int maxCount = length / 2 < sprites.Length ? 1 : length / 2 % sprites.Length;

        for (int i = 0; i < length / 2; i++)
        {
            int value = -1;
            do
            {
                value = Random.Range(0, sprites.Length);
            } while (pool.FindAll(x => x == value).Count() > (maxCount));
            pool.Add(value);
            pool.Insert(0, value);
        }

        //shufle list to random position item
        for (int i = 0; i < length; i++)
        {
            int index1 = Random.Range(0, length);
            int index2 = Random.Range(0, length);
            int temp = pool[index1];
            pool[index1] = pool[index2];
            pool[index2] = temp;
        }
//        Debug.Log(minx + "  " + miny + "  " +cellWidth +"   "+ cellHeight);
       
        // default maps data is -1
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                Vector2 pos = GetPos(i, j);
                cellDatas[i, j] = new CellData(i, j, -1, pos);
            }
        }

        // create item object and set type object
        int id = 0;
        for (int j = 1; j < height - 1; j++)
        {
            for (int i = width - 2; i > 0; i--)
            {
                int type = pool[id];
                id++;

                CellItem cellItem = CreateItem(type, i, j);
                cellItems.Add(cellItem);
                cellDatas[i, j].cellType = type;

            }
        }
        if (!CheckAnswer())
        {
            OnSwap();
        }

    }

    void SortList()
    {
        cellItems = cellItems.OrderByDescending(x => x.posY).ThenBy(x => x.posX).ToList();
        for (int i = 0; i < cellItems.Count; i++)
        {
            cellItems[i].transform.SetSiblingIndex(i);
        }
    }

    /// <summary>
    /// Create Item object
    /// </summary>
    /// <param name="type"></param>
    /// <param name="i"></param>
    /// <param name="j"></param>
    /// <returns></returns>
    CellItem CreateItem(int type, int i, int j)
    {
        GameObject go = ContentMgr.Instance.GetItem("Cell");
        go.transform.SetParent(gridParent);

        go.GetComponent<RectTransform>().sizeDelta = new Vector2(1 * cellWidth, 1 * cellHeight);
        go.transform.localScale = Vector3.one;
     
        go.name = (i + "" + j).ToString();
        CellItem item = go.GetComponent<CellItem>();
        Sprite sprite = sprites[type];
        item.Init(this, i, j, type, sprite);
        return item;
    }


    /// <summary>
    /// Call when select item
    /// </summary>
    /// <param name="item"></param>
    public void OnPressItem(CellItem item)
    {
        if (firstSelected == null)
        {
            firstSelected = item;
        }
        else
        {
            if (firstSelected.posX == item.posX && firstSelected.posY == item.posY)    //  select object again
            {
                firstSelected = null;
                return;
            }

            List<CellData> path = CheckPath(firstSelected, item);  // check path 

            if (path != null)
            {
                // destroy end draw line folow path
                OnPair(path, firstSelected, item);
            }
            else
            {
                AudioManager.Instance.Shot("false");
                firstSelected.OnDeselected();
                item.OnDeselected();
                firstSelected = null;
            }
        }

    }

    IEnumerator UpdateCellData()
    {
        yield return new WaitForSeconds(0.5f);

        foreach (CellData item in cellDatas)
        {
            CellItem cellItem = cellItems.Find(x => x.posX == item.posX && x.posY == item.posY);
            if (cellItem)
            {
                item.cellType = cellItem.cellType;
            }
            else
            {
                item.cellType = -1;
            }
        }

        if (!CheckAnswer())
        {
            OnSwap();
        }

    }

    IEnumerator MoveItem(CellItem firstItem, CellItem secondItem, float time)
    {
        yield return new WaitForSeconds(time);
        float mid = (width - 1) / 2f;
        List<CellItem> list = null;
        switch (moveMode)
        {
            case MoveMode.Idle:
                break;
            case MoveMode.Up:
                if (firstItem.posY > secondItem.posY)
                {
                    list = cellItems.FindAll(x => x.posY < secondItem.posY && x.posX == secondItem.posX);
                    list.AddRange(cellItems.FindAll(x => x.posY < firstItem.posY && x.posX == firstItem.posX));
                }
                else
                {
                    list = cellItems.FindAll(x => x.posY < firstItem.posY && x.posX == firstItem.posX);
                    list.AddRange(cellItems.FindAll(x => x.posY < secondItem.posY && x.posX == secondItem.posX));
                }

                MoveItemList(list, Move.Up);

                break;
            case MoveMode.Right:
                if (firstItem.posX > secondItem.posX)
                {
                    list = cellItems.FindAll(x => x.posX < secondItem.posX && x.posY == secondItem.posY);
                    list.AddRange(cellItems.FindAll(x => x.posX < firstItem.posX && x.posY == firstItem.posY));
                }
                else
                {
                    list = cellItems.FindAll(x => x.posX < firstItem.posX && x.posY == firstItem.posY);
                    list.AddRange(cellItems.FindAll(x => x.posX < secondItem.posX && x.posY == secondItem.posY));
                }
                MoveItemList(list, Move.Right);
                break;
            case MoveMode.Dow:
                if (firstItem.posY > secondItem.posY)
                {
                    list = cellItems.FindAll(x => x.posY > secondItem.posY && x.posX == secondItem.posX);
                    list.AddRange(cellItems.FindAll(x => x.posY > firstItem.posY && x.posX == firstItem.posX));
                }
                else
                {
                    list = cellItems.FindAll(x => x.posY > firstItem.posY && x.posX == firstItem.posX);
                    list.AddRange(cellItems.FindAll(x => x.posY > secondItem.posY && x.posX == secondItem.posX));
                }
                MoveItemList(list, Move.Dow);
                break;
            case MoveMode.Left:
                if (firstItem.posX > secondItem.posX)
                {
                    list = cellItems.FindAll(x => x.posX > secondItem.posX && x.posY == secondItem.posY);
                    list.AddRange(cellItems.FindAll(x => x.posX > firstItem.posX && x.posY == firstItem.posY));
                }
                else
                {
                    list = cellItems.FindAll(x => x.posX > firstItem.posX && x.posY == firstItem.posY);
                    list.AddRange(cellItems.FindAll(x => x.posX > secondItem.posX && x.posY == secondItem.posY));
                }
                MoveItemList(list, Move.Left);
                break;
            case MoveMode.InToOut:
                if (firstItem.posX > mid && secondItem.posX > mid)
                {
                    if (firstItem.posX > secondItem.posX)
                    {

                      
                        MoveInToOut(secondItem);
                        MoveInToOut(firstItem);
                    }
                    else
                    {

                        
                        MoveInToOut(firstItem);
                        MoveInToOut(secondItem);
                    }

                }
                else if (firstItem.posX < mid && secondItem.posX < mid)
                {
                    if (firstItem.posX < secondItem.posX)
                    {

                      
                        MoveInToOut(secondItem);
                        MoveInToOut(firstItem);
                    }
                    else
                    {

                        
                        MoveInToOut(firstItem);
                        MoveInToOut(secondItem);
                    }
                }
                else
                {
                    MoveInToOut(firstItem);
                    MoveInToOut(secondItem);
                }


                break;
            case MoveMode.OutToIn:


                if (firstItem.posX < mid && secondItem.posX < mid)
                {
                    if (firstItem.posX > secondItem.posX)
                    {
                        MoveOutToIn(secondItem);
                        MoveOutToIn(firstItem);
                    }
                    else
                    {
                        MoveOutToIn(firstItem);
                        MoveOutToIn(secondItem);

                    }
                }
                else if (firstItem.posX > mid && secondItem.posX > mid)
                {
                    if (firstItem.posX < secondItem.posX)
                    {
                        MoveOutToIn(secondItem);
                        MoveOutToIn(firstItem);
                    }
                    else
                    {
                        MoveOutToIn(firstItem);
                        MoveOutToIn(secondItem);

                    }
                }
                else
                {
                    MoveOutToIn(firstItem);
                    MoveOutToIn(secondItem);
                }
                break;
            default:
                break;
        }

        StartCoroutine(UpdateCellData());
        SortList();
    }


    void MoveOutToIn(CellItem cellItem)
    {
        float mid = (width - 1) / 2f;
        List<CellItem> list = null;
        if (cellItem.posX >= mid)
        {
            list = cellItems.FindAll(x => x.posX > cellItem.posX && x.posY == cellItem.posY);
            MoveItemList(list, Move.Left);
        }
        else if (cellItem.posX < mid)
        {
            list = cellItems.FindAll(x => x.posX < cellItem.posX && x.posY == cellItem.posY);
            MoveItemList(list, Move.Right);
        }
        else
            return;

    }

    void MoveInToOut(CellItem cellItem)
    {
        float mid = (width - 1) / 2f;
        List<CellItem> list = null;
        if (cellItem.posX >= mid)
        {
            list = cellItems.FindAll(x => x.posX >= mid && x.posX < cellItem.posX && x.posY == cellItem.posY);
            MoveItemList(list, Move.Right);
        }
        else if (cellItem.posX < mid)
        {
            list = cellItems.FindAll(x => x.posX > cellItem.posX && x.posX < mid && x.posY == cellItem.posY);
            MoveItemList(list, Move.Left);
        }
        else
            return;

    }



    void MoveItemList(List<CellItem> cellItems, Move move)
    {
        foreach (CellItem item in cellItems)
        {
            item.MoveItem(move);
        }
    }

    void OnPair(List<CellData> path, CellItem firstItem, CellItem secondItem)
    {
        AudioManager.Instance.Shot("true");
        CellData first = new CellData(firstItem);
        CellData second = new CellData(secondItem);
        cellItems.Remove(firstItem);
        cellItems.Remove(secondItem);

        //destroy paire
        // Destroy(firstItem.gameObject, 0.2f);
        ContentMgr.Instance.Despaw(firstItem.gameObject, 0.2f);
        // PoolManager.Pools["Pikachu"].Despawn(firstItem.transform,0.2f);
        // Destroy(secondItem.gameObject, 0.2f);
        ContentMgr.Instance.Despaw(secondItem.gameObject, 0.2f);
        // PoolManager.Pools["Pikachu"].Despawn(secondItem.transform, 0.2f);

        StartCoroutine(MoveItem(firstItem, secondItem, 0.25f));


        path.Add(second);
        path.Insert(0, first);
        DrawLineConnect(path);


        //reset first selected
        firstSelected = null;

        //Reset celltype data
        cellDatas[firstItem.posX, firstItem.posY].cellType = -1;
        cellDatas[secondItem.posX, secondItem.posY].cellType = -1;

        this.PostEvent((int)EventID.UpdateScore, 10);


        CheckWin();
    }

    /// <summary>
    /// Draw line connect
    /// </summary>
    /// <param name="path"></param>
    void DrawLineConnect(List<CellData> path)
    {
        line.DrawLine(path);
    }

    void CheckWin()
    {
        if (cellItems.Count <= 0)
            gameMgr.LeveFinish();
    }

    /// <summary>
    /// check answer 
    /// </summary>
    /// <returns></returns>
    bool CheckAnswer()
    {
        if (cellItems.Count <= 0)
            return true;

        for (int i = 0; i < cellItems.Count - 1; i++)
        {
            for (int j = i + 1; j < cellItems.Count; j++)
            {
                List<CellData> path = CheckPath(cellItems[i], cellItems[j]);
                if (path != null)
                {
                    return true;
                }
            }
        }

        return false;
    }

    public void Trick()
    {
        if (cellItems.Count > 0)
        {
            for (int i = 0; i < cellItems.Count - 1; i++)
            {
                for (int j = i + 1; j < cellItems.Count; j++)
                {
                    List<CellData> path = CheckPath(cellItems[i], cellItems[j]);
                    if (path != null)
                    {
                        OnPair(path, cellItems[i], cellItems[j]);
                        return;
                    }
                }
            }
        }

    }

    public void GetHint()
    {
        videoAdid = VideData.Instance.GetVide();
        TTSDK.TTRewardedVideoAd r = AdMgr.Instance.ShowVideoAdNew(videoAdid);
        // 暂停游戏
        Time.timeScale = 0f;
        //创建激励视频关闭回调
        r.OnClose += (bol, val) =>
        {
            Debug.Log("关闭广告 ，是否已经看完" + bol);
            //看完广告获得提示
            if (bol)
            {
                Time.timeScale = 1.0f;
                GameDataMgr.Hint++;
                MaidianNew.MaidianBackCallback(" ");
                Debug.Log("广告看完");
            }
            else
            {
                Time.timeScale = 1.0f;
                Debug.Log("广告未看完");
            }
        };

        //创建报错回调  
        r.OnError += (code, errorMessage) =>
        {
            Time.timeScale = 1.0f;
            Debug.Log("code:" + code + "错误信息：" + errorMessage);
        };

        //展示广告（新版本必须调用，不然无法展示出来广告）
        r.Show();   
    }

    public void Hint()
    {
        if (GameDataMgr.Hint <= 0)
        {

            return;
        }

        //AdAssistant.Instance.SetCallBackFullScreen
        //(
            //() =>
            //{
                //AdAssistant.Instance.RequestFullScreen();
                GameMgr.Instance.isPlay = true;
                if (cellItems.Count > 0)
                {
                    for (int i = 0; i < cellItems.Count - 1; i++)
                    {
                        for (int j = i + 1; j < cellItems.Count; j++)
                        {
                            List<CellData> path = CheckPath(cellItems[i], cellItems[j]);
                            if (path != null)
                            {
                                cellItems[i].Hint();
                                cellItems[j].Hint();
                                GameDataMgr.Hint--;
                                this.PostEvent(EventID.UpdateHint, GameDataMgr.Hint);
                                //   OnPair(path, cellItems[i], cellItems[j]);
                                return;
                            }
                        }
                    }
                }
            //}
        //);
        GameMgr.Instance.isPlay = false;
        //AdAssistant.Instance.ShowFullScreen();
       
        
       
    }

    public void Swap()
    {
        Debug.Log(gameMgr.resetCount);
        if (gameMgr.resetCount <= 0)
        {
            return;
        }
        //AdAssistant.Instance.SetCallBackFullScreen
        //(
            //() =>
            //{
                //GameMgr.Instance.isPlay = true;
                OnSwap();
              
                //AdAssistant.Instance.RequestFullScreen();
            //});
        //GameMgr.Instance.isPlay = false;
        //AdAssistant.Instance.ShowFullScreen();
    }


    /// <summary>
    /// swap item if not answer
    /// </summary>
    public void OnSwap()
    {

        gameMgr.UpdateResetCount();
        // swap

        do
        {
            int n = cellItems.Count;
            while (n > 1)
            {
                n--;
                int k = Random.Range(0, n + 1);

                int type = cellItems[n].cellType;
                cellItems[n].cellType = cellItems[k].cellType;
                cellItems[k].cellType = type;
            }

        } while (!CheckAnswer());

        foreach (CellItem item in cellItems)
        {
            //if(item!=null)
            item.UpdateSprite(sprites[item.cellType]);
            cellDatas[item.posX, item.posY].cellType = item.cellType;
        }


    }


    /// <summary>
    /// Check 2 point are pair
    /// </summary>
    /// <param name="first"></param>
    /// <param name="second"></param>
    List<CellData> CheckPath(CellItem firstItem, CellItem secondItem)
    {
        CellData first = new CellData(firstItem);
        CellData second = new CellData(secondItem);

        List<CellData> result = new List<CellData>();
        if (first.cellType != second.cellType)
        {
            return null;
        }
        if (CheckNearby(first, second))
        {
            result.Add(first);
            result.Add(second);
            return result;
        }
        float distance = width * height;
        bool find = false;
        CellData point1 = null, point2 = null;
        List<CellData> cellsEnableFirst = GetCellsEnableFromCell(first);
        List<CellData> cellsEnableSecond = GetCellsEnableFromCell(second);
        for (int i = 0; i < cellsEnableFirst.Count; i++)
        {
            for (int j = 0; j < cellsEnableSecond.Count; j++)
            {
                if (CheckPathLine(cellsEnableFirst[i], cellsEnableSecond[j]))
                {
                    if (Distance(cellsEnableFirst[i], cellsEnableSecond[j]) < distance)
                    {
                        point1 = cellsEnableFirst[i];
                        point2 = cellsEnableSecond[j];
                        find = true;
                        distance = Distance(cellsEnableFirst[i], cellsEnableSecond[j]);
                    }

                }
            }
        }
        if (find)
        {
            result.Add(point1);
            result.Add(point2);
            return result;
        }
        else
        {
            return null;
        }

    }

    float Distance(CellData first, CellData second)
    {
        return Vector2.Distance(new Vector2(first.posX, first.posY), new Vector2(second.posX, second.posY));
    }

    /// <summary>
    /// check nearby
    /// </summary>
    /// <param name="first"></param>
    /// <param name="second"></param>
    /// <returns></returns>

    bool CheckNearby(CellData first, CellData second)
    {
        if (first.posX == second.posX && Mathf.Abs(first.posY - second.posY) == 1)
        {
            return true;
        }
        else if (first.posY == second.posY && Mathf.Abs(first.posX - second.posX) == 1)
        {
            return true;
        }
        return false;
    }

    /// <summary>
    /// Get cell list enable from cell
    /// </summary>
    /// <param name="from"></param>
    /// <returns></returns>
    List<CellData> GetCellsEnableFromCell(CellData from)
    {
        List<CellData> result = new List<CellData>();
        // for right
        for (int i = from.posX + 1; i < width; i++)
        {
            CellData cell = cellDatas[i, from.posY];
            if (cell.cellType != -1)
                break;
            if (CheckPathLine(from, cell))
                result.Add(cell);
        }
        //for left
        for (int i = from.posX - 1; i >= 0; i--)
        {
            CellData cell = cellDatas[i, from.posY];
            if (cell.cellType != -1)
                break;
            if (CheckPathLine(from, cell))
                result.Add(cell);
        }

        //for up
        for (int i = from.posY + 1; i < height; i++)
        {
            CellData cell = cellDatas[from.posX, i];
            if (cell.cellType != -1)
                break;
            if (CheckPathLine(from, cell))
                result.Add(cell);
        }

        //for down
        for (int i = from.posY - 1; i >= 0; i--)
        {
            CellData cell = cellDatas[from.posX, i];
            if (cell.cellType != -1)
                break;
            if (CheckPathLine(from, cell))
                result.Add(cell);
        }
        return result;
    }


    /// <summary>
    /// Check path line 2 point
    /// </summary>
    /// <param name="to"></param>
    /// <param name="from"></param>
    /// <returns></returns>
    bool CheckPathLine(CellData to, CellData from)
    {
        //if (to.posX == from.posX && to.posY == from.posY)
        //    return true;
        if (to.posX == from.posX)
        {
            int min = Mathf.Min(to.posY, from.posY);
            int max = Mathf.Max(to.posY, from.posY);
            for (int i = min; i <= max; i++)
            {
                if (i == to.posY)
                    continue;
                if (cellDatas[to.posX, i].cellType != -1)
                    return false;
            }
        }
        else if (to.posY == from.posY)
        {
            int min = Mathf.Min(to.posX, from.posX);
            int max = Mathf.Max(to.posX, from.posX);
            for (int i = min; i <= max; i++)
            {
                if (i == to.posX)
                    continue;
                if (cellDatas[i, to.posY].cellType != -1)
                    return false;
            }
        }
        else
            return false;
        return true;
    }
}
